package com.alan.validate.aop;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import org.apache.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import com.alan.validate.comment.AutoBack;
import com.alan.validate.config.ErrMessageConfig;
import com.alan.validate.constraints.Impl.Constraint;
import com.alan.validate.model.BindResult;
import com.alan.validate.model.IValidErrorEntiy;
import com.alan.validate.util.ParamValidate;

@Aspect
public class ParamValidateBean {
	
	Logger logger = Logger.getLogger(ParamValidateBean.class);
	
	//校验失败时是否自动返回
	public  boolean autoBack = false;	

	@Around("@annotation(com.alan.validate.aop.Validate)")
	private Object around(ProceedingJoinPoint joinPoint) throws Throwable {
		logger.debug("ParamValidateBean -- start");
		MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
		Method method = methodSignature.getMethod();
		Annotation[] as1 = method.getAnnotations();
		//得到参数注解
		Annotation[][] an = method.getParameterAnnotations();
		// 得到所有的参数名
		String[] paramName = methodSignature.getParameterNames();
		// 得到所有的参数值
		Object[] o = joinPoint.getArgs();
		BindResult b = new BindResult();
		if (an.length > 0) {
			// 注解
			for (int i = 0; i < an.length; i++) {
				for (int j = 0; j < an[i].length; j++) {
					Annotation a = an[i][j];
					Constraint constraint = null;
					String str = a.annotationType().toString();
					String[] arr = str.split("[ ]");
					String className = arr[1];
					logger.debug("ParamValidateBean className="+className);
					//Annotation[] at = Class.forName(className).getAnnotations();
					constraint = Class.forName(className).getAnnotation(Constraint.class);
					if(constraint == null){
						continue;
					}
					logger.debug("ParamValidateBean constraint="+className);
					Class p = constraint.validatedBy();
					ParamValidate pValidate = (ParamValidate) p.newInstance();
					pValidate.initialize(a);
					if(pValidate.isValid(o[i])){
						//success
						b.setHasError(false);
						logger.debug("ParamValidateBean not has Error!");
					}else{
						//fail
						b.setHasError(true);
						Method method2 = a.getClass().getMethod("message");
						String msg = (String) method2.invoke(a);
						if("".equals( msg )){
							msg = paramName[i]+":"+ErrMessageConfig.getProperties( className );
						}
						b.setFildName(paramName[i]);
						b.setErrMsg(msg);
						logger.debug("ParamValidateBean has Error! fildName="+paramName[i]+"; msg="+msg);
						break;
					}
				}
				if(b.getHasError()){
					break;
				}
			}
		}
		if(b.getHasError()){
			logger.debug("ParamValidateBean has error!");
			for (Annotation annotation : as1) {
				if(annotation instanceof Validate){
					Validate resValidate = (Validate) annotation;
					AutoBack isAutoBack = resValidate.autoBack();
					autoBack=isAutoBack.equals(AutoBack.FOLLOW_SETTING)?autoBack
							:isAutoBack.equals(AutoBack.ENABLE)?true:false;
					if(!autoBack){
						logger.debug("ParamValidateBean -- is not autoBack");
						break;
					}
					Class<?> returnClz=method.getReturnType();
					if(returnClz.newInstance() instanceof IValidErrorEntiy){
						IValidErrorEntiy entiy = (IValidErrorEntiy) returnClz.newInstance();
						Object object = entiy.ReturnMessage(b.getErrMsg());
						logger.debug("ParamValidateBean -- is autoBack end return");
						return object;
					} else{
						throw new IllegalArgumentException("The return type is not IValidErrorEntiy type!");
					}
				}
			}
		}
		logger.debug("ParamValidateBean is not error!");
		if (o[o.length - 1] instanceof BindResult) {
			o[o.length - 1] = b;
		}
		Object result=joinPoint.proceed(o);
		logger.debug("ParamValidateBean -- end return");
		return result;
	}

	
	
	
	public boolean isAutoBack() {
		return autoBack;
	}

	public void setAutoBack(boolean autoBack) {
		this.autoBack = autoBack;
	}
}
